package com.ruoyi.common.tenant.component;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.ruoyi.common.core.enums.MultiTenantEnums;
import com.ruoyi.common.core.event.DefaultMultiTenantPublish;
import com.ruoyi.common.core.event.MultiTenantEvent;
import com.ruoyi.common.core.event.SysTenantDTO;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.common.tenant.cache.TenantDataSourceMappingHoulder;
import com.ruoyi.common.tenant.domain.DataSourceInfo;
import com.ruoyi.common.tenant.domain.SysTenant;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;

@Component
@Slf4j
public class TenantDataSourceManager {

    @Resource
    private DataSource dataSource;
    @Resource
    private DefaultMultiTenantPublish defaultMultiTenantPublish;

    /**
     * 刷新数据源
     *
     * @param sysTenants 变更后的数据源列表
     */
    public synchronized void refreshDataSource(List<SysTenant> sysTenants) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        sysTenants.forEach(tenant -> {
            boolean exist = TenantDataSourceMappingHoulder.containsTenantId(tenant.getTenantId());
            DataSourceInfo dataSourceInfo = JSON.parseObject(tenant.getDataSource(), DataSourceInfo.class);
            if (exist) {
                SysTenant stsTenant = TenantDataSourceMappingHoulder.getStsTenant(tenant.getTenantId());
                if (ObjectUtils.isNotEmpty(stsTenant)
                        && StringUtils.isNotEmpty(stsTenant.getMd5())
                        && !stsTenant.getMd5().equalsIgnoreCase(tenant.getMd5())) {

                    SysTenantDTO sysTenantDTO = new SysTenantDTO();
                    BeanUtils.copyProperties(tenant,sysTenantDTO);
                    defaultMultiTenantPublish.publishTenant(new MultiTenantEvent(MultiTenantEnums.UPDATE,tenant.getTenantId(),sysTenantDTO));
                    dynamicDataSource(ds, tenant, dataSourceInfo);
                    log.info("refresh dataSource success! befor:[{}],after:[{}]", stsTenant, tenant);
                }
            } else {
                SysTenantDTO sysTenantDTO = new SysTenantDTO();
                BeanUtils.copyProperties(tenant,sysTenantDTO);
                defaultMultiTenantPublish.publishTenant(new MultiTenantEvent(MultiTenantEnums.INSERT,tenant.getTenantId(),sysTenantDTO));
                dynamicDataSource(ds, tenant, dataSourceInfo);
                log.info("add dataSource success! tenant: [{}] ", tenant);
            }
        });
    }

    @SneakyThrows
    public void dynamicDataSource(DynamicRoutingDataSource ds, SysTenant tenant, DataSourceInfo dataSourceInfo) {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(dataSourceInfo.getUrl());
        datasource.setUsername(dataSourceInfo.getUsername());
        datasource.setPassword(dataSourceInfo.getPassword());
        datasource.setDriverClassName(dataSourceInfo.getDriverClassName());
        ds.addDataSource(tenant.getDataSourceKey(), datasource);
        ds.afterPropertiesSet();
        TenantDataSourceMappingHoulder.addMapping(tenant.getTenantId(), tenant);
    }
}
